<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Dexcalibur - Application object finder</title>

    <!--## pages/inc/tpl_css.html ##-->

    <!--## pages/inc/tpl_js_d3.html ##-->


    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

</head>

<body class="dxc-dark">

    <div id="wrapper">

        <!--## pages/inc/menu.html ##-->
        <!--            <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Hooks<span class="caret"></span></a>
                            <ul class="dropdown-menu">
                              <li><a href="#">Control</a></li>
                              <li role="separator" class="divider"></li>
                              <li><a href="#">Single device logs</a></li>
                              <li><a href="#">Multi devices logs</a></li>
                              <li><a href="#">Observed files</a></li>
                              <li role="separator" class="divider"></li>
                              <li><a href="#">Strategies</a></li>
                            </ul>
                          </li>
                        <li>
                        -->

        <div id="page-wrapper" class="dxc-dark">
            <!--<div class="row">
                <div class="col-lg-12">
                    <h1 class="page-header">Application object finder</h1>
                </div>
            </div>-->

        <!--<div class="row">
            <div class="col-lg-4">
                <div class="card">
                    <ul class="list-group">
                        <li>Search</li>
                        <li>Keystores</li>
                        <li>Cryptographic constants</li>
                    </ul>
                </div>
            </div>
            <div class="col-lg-8">
                test2
            </div>
        </div>-->
            <!-- /.row -->
            <div class="card">
                <div class="card-body">
                    <div class="input-group">
                        <input type="text" class="form-control" placeholder='class("name:Keystore")' id="search_request">
                        <span class="input-group-append">
                            <button class="btn btn-primary" id="button_search" type="button">
                                <span class="fa fa-search">&nbsp;</span>
                                Search
                            </button>
                            <button class="btn btn-danger" id="button_probeall" type="button">
                                <span class="fa fa-bolt">&nbsp;</span>
                                Probe all
                            </button>
    
                        </span>
                    </div>
                </div>

                <div class="card-footer">
                        <!--<b>Search helper (click for add a filter) : </b>-->
                            <div class="pre-request">
                                <span>Search :</span>
                                <span class="badge badge-pill badge-danger prefilter-clean">clean</span>
                                <span class="badge badge-pill badge-primary prefilter" prefilt='call("calleed.name:@@")'>find calls to a method</span>
                                <span class="badge badge-pill badge-info prefilter" prefilt='call("calleed.name:@@").select("caller")'>find callers of a method</span>
                                <span class="badge badge-pill badge-info prefilter" prefilt='call("calleed.name:@@").filter("calleed.__signature__:->")'>use of the field</span>
                                <span class="badge badge-pill badge-info prefilter" prefilt='class("extends.name:@@")'>find class by extended class</span>
                                
                                <span class="badge badge-pill badge-warning prefilter" prefilt='class("name:@@")'>find class by name</span>
                                <span class="badge badge-pill badge-warning prefilter" prefilt='field("name:@@")'>find field by name</span>
                                <span class="badge badge-pill badge-warning prefilter" prefilt='method("name:@@")'>find method by name</span>
                                <span class="badge badge-pill badge-info prefilter" prefilt='method("args.__signature__:@@")'>find method by arg type</span>
                                <span class="badge badge-pill badge-info prefilter" prefilt='method("ret.__signature__:@@")'>find method by return type</span>
                                
                                <span class="badge badge-pill badge-info prefilter" prefilt='string("value:@@")'>Strings containing</span>
                                <span class="badge badge-pill badge-pink prefilter" prefilt='array("uid:@@")'>static array by method</span>
                                <span class="badge badge-pill badge-pink prefilter" prefilt='array("tags:@@")'>static array by tag</span>

                                <span class="badge badge-pill badge-purple prefilter" prefilt='string("tags:URI").union($.project.find.string("tags:URI"))'>URI</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='array("tags:IP")'>IP</span>
                                <span class="prefilter-more">&nbsp;advanced search ...</a>

                            </div>
                            <div class="pre-filter" style="display:none">
                                <span>Filter :</span>
                                <span class="badge badge-pill badge-danger prefilter-clean">clean</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='select("_callers")'>xref</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='select("caller")'>keep callers</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='select("calleed")'>keep calleds</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='filter("enclosingClass.name:^@@")'>filter by package</span>
                                <span class="badge badge-pill badge-purple prefilter" prefilt='filter("caller.enclosingClass.name:@@")'>filter by caller class</span>
                                <span class="badge badge-pill badge-purple prefilter" when="before" prefilt='nocase()'>Case ensensitive</span>
                            </div>
                    </div>

                    <div class="card-footer" id="request-helper" style="display:none">
                        <div class="row">
                            <div class="col-lg-10">
                                Search ...
                            </div>
                            <div class="col-lg-2">
                                <button class="btn btn-sm" id="request-helper-view-reset">
                                    <span class="fa fa-refresh"></span>&nbsp;Reset
                                </button>
                                <button class="btn btn-sm" id="request-helper-view-cancel">
                                    <span class="fa fa-close"></span>&nbsp;Cancel
                                </button>
                            </div>
                        </div>

                        <div class="row" id="request-helper-view" style="margin-left:1em;width:70pc;"></div>  
                    </div>
            </div>


            <div class="card">
                <table width="100%"  class="table table-striped table-bordered table-hover finderTable" id="dataTables-finder">
                    <thead>
                        <tr>
                            <th id="finder-col1" class="col-lg-1">-</th>
                            <th id="finder-col2" class="col-lg-4">-</th>
                            <th id="finder-col3" class="col-lg-4">-</th>
                            <th id="finder-col4" class="col-lg-3">-</th>
                        </tr>
                    </thead>
                    <tbody>
                        
                    </tbody>
                </table>
            </div>
            <!-- /.row -->
        </div>
        <!-- /#page-wrapper -->

        <div class="modal fade" id="probeall_modal" tabindex="-1" role="dialog" aria-labelledby="probeallModalLabel" aria-hidden="true">
            <div class="modal-dialog modal-lg" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 class="modal-title" id="probeallModalLabel">Confirmation</h3>
                    </div>
                    <div class="modal-body">
                        Are you sure to probe <b id="probeall_count"></b> methods ?
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-danger" data-dismiss="modal">Abort</button>
                        <button type="button" class="btn btn-success confirm">Confirm</button>
                    </div>
                </div>
            </div>
        </div>

        <div class="modal modal-default" style="display:none" id="class-panel">
            <div class="modal-header">

            </div>
            <div class="modal-body">

            </div>
        </div>


    </div>
    <!-- /#wrapper -->

    <div class="modal fade" id="renameModal" tabindex="-1" role="dialog" aria-labelledby="renameModalLabel" aria-hidden="true">
        <div class="modal-dialog" role="document">
          <div class="modal-content">
                <div class="modal-header">
                  <h3 class="modal-title">Rename</h3>
                </div>
            <div class="modal-body">
                <div class="input-group mb-8">
                <input type="text" id="renameModalAlias" class="form-control" style="width:30em" autofocus="autofocus" placeholder="Alias" aria-label="Alias" aria-describedby="basic-addon1">
                <input type="hidden" id="renameModalSubject" class="form-control" style="width:30em" aria-describedby="basic-addon1">
                <input type="hidden" id="renameModalType" class="form-control" style="width:30em" aria-describedby="basic-addon1">
                </div>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>&nbsp;
              <button type="button" class="btn btn-primary aliasconfirm">Save</button>
            </div>
          </div>
        </div>
      </div>

    <div class="modal fade" id="xrefModal" tabindex="-1" role="dialog" aria-labelledby="xrefModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <h3 class="modal-title" id="xrefModalLabel">XRefs</h3>
            </div>
            <div class="modal-body">
                <div name="d3xref" id="d3xref"></div>
                <table width="100%"  class="table table-striped table-bordered table-hover" id="dataTables-xref">
                    <thead>
                        <tr>
                            <th id="xref-col0" class="col-lg-1">Type</th>
                            <th id="xref-col1" class="col-lg-8">Name</th>
                            <th id="xref-col2" class="col-lg-1">Tags</th>
                            <th id="xref-col3" class="col-lg-2 col-action">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        
                    </tbody>
                </table>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
          </div>
        </div>
      </div>

      <div class="modal fade" id="gsetterModal" tabindex="-1" role="dialog" aria-labelledby="gsetterModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <h3 class="modal-title" id="gsetterModalLabel">Getter</h3>
            </div>
            <div class="modal-body">
                <table width="100%"  class="table table-striped table-bordered table-hover" id="dataTables-gsetter">
                    <thead>
                        <tr>
                            <th id="xref-col0" class="col-lg-1">Type</th>
                            <th id="xref-col1" class="col-lg-5">Method</th>
                            <th id="xref-col2" class="col-lg-2">Tags</th>
                            <th id="xref-col3" class="col-lg-2 col-action">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        
                    </tbody>
                </table>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
          </div>
        </div>
      </div>

      <div class="modal fade" id="newHookModal" tabindex="-1" role="dialog" aria-labelledby="newHookModalLabel" aria-hidden="true">
            <div class="modal-dialog" role="document">
              <div class="modal-content">
                <div class="modal-header">
                  <h3 class="modal-title" id="newHookModalLabel">Hook configuration</h3>
                </div>
                <div class="modal-body">
                    <div class="row" style="margin-bottom: 1em">
                        <div class="col-lg-3">Location :</div>
                        <div class="col-lg-3">
                                <div class="custom-control custom-switch">
                                    <input type="checkbox" class="custom-control-input" id="hookconfBefore">
                                    <label class="custom-control-label" for="hookconfBefore">Before</label>
                                </div>
                                <div class="custom-control custom-switch">
                                    <input type="checkbox" class="custom-control-input" id="hookconfAfter">
                                    <label class="custom-control-label" for="hookconfAfter">After</label>
                                </div>
                                <div class="custom-control custom-switch">
                                    <input type="checkbox" class="custom-control-input" id="hookconfReplace">
                                    <label class="custom-control-label" for="hookconfReplace">Replace</label>
                                </div>
                        </div>
                        <div class="col-lg-3 dxc-form-separator">Frida API :</div>
                        <div class="col-lg-3">
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="radio" name="hookconfAPI" id="hookconfApiJS" value="js" checked>
                                    <label class="form-check-label" for="hookconfApiJS">JS</label>
                                    </div>
                                    <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="radio" name="hookconfAPI" id="hookconfApiC" value="c" disabled>
                                    <label class="form-check-label" for="hookconfApiC">C (todo)</label>
                                    </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-lg-12 dxc-horizon-separator">
                                <label for="inputState">Breakpoint (option)</label>

                                <select id="inputState" class="form-control">
                                    <option selected>Choose...</option>
                                    <option>java.lang.String()</option>
                                </select>
                              
                                <!--<div class="form-group col-md-2">
                                        <button class="btn btn-primary mb-2">New</button>
                                </div>-->
                            </form>
                        </div>
                    </div>
                
               
                </div>
                <div class="modal-footer">
                  <button type="button" class="btn btn-secondary" data-dismiss="modal">
                    <span class="fa fa-close"></span>&nbsp;Cancel</button>
                  <button type="button" class="btn btn-primary" data-dismiss="modal">
                      <span class="fa fa-pencil"></span>&nbsp;Edit code (optional)</button>
                  <button type="button" class="btn btn-success" data-dismiss="modal">
                      <span class="fa fa-bolt"></span>&nbsp;Deploy</button>
                </div>
              </div>
            </div>
          </div>
    <!--## pages/inc/tpl_js_end.html ##-->
    <!--## pages/inc/tpl_ace_smali.html ##-->

    <script>

    function setupAceEditor(id){
        var editor = ace.edit(id);
        editor.setTheme("ace/theme/monokai2"); //
//        editor.setTheme("ace/theme/solarized_light"); //

        editor.setOptions({
            maxLines: 50, 
            fontSize: "12pt"
        });
        //editor.setUseWorker(false);
        editor.session.setMode("ace/mode/smali");
    }

    function changeAceLanguage(pID, pLang){
        var editor = ace.edit(pID);
        editor.session.setMode("ace/mode/"+pLang);
    }

    function changeAceEditor(id, code){
        var editor = ace.edit(id);
        editor.setValue(code);
    }


    var IdRegister = new Wexcalibur();
     

    function htmlEncode(txt){
        return $('<div />').text(txt).html();
    }

    /* Formatting function for row details - modify as you need */
    function format ( row ) {
        // `d` is the original data object for the row
        let body = '';

        body += "<code style='margin:10px'>";
        body += $("<div />").text(decodeURIComponent(atob(row.script))).html();
        body += "</code>"
            
        return body;
    }


    function getStubType(id){
        let STUB_TYPE=[
            "METHOD",
            "FIELD",
            "ANNOTATION",
            "INSTR",
            "MISSING",
            "CLASS",
            "OBJ_TYPE",
            "BASIC_TYPE",
            "VALUE_CONST",
            "STRING_VALUE",
            "CIRCULAR",
            "VARIABLE",
            "CALL"
        ];

        return STUB_TYPE[id-1];
    }


    var ApplicationMap = {
        tags: null
    };

    const BS = {
        color: {
            purple: 'purple',       
            pink: 'pink',  
            primary: 'primary',         
            info: 'info',         
            warning: 'warning',         
            danger: 'danger',         
            secondary: 'secondary',
            success:'success'          
        },
        badge: function(color,data){
            if(BS.color[color]==null) console.error("Given color not exists : ",color);

            return '&nbsp;<span class="badge badge-pill badge-'+BS.color[color]+'">'+htmlEncode(data)+'</span>'; 
        },
        modifiers: function(mods){
            let b="";
            if(mods.private) b+="<i style='color:#F00'>private</i>&nbsp;";
            if(mods.protected) b+="<i style='color:orange'>protected</i>&nbsp;";
            if(mods.abstract) b+="<i style='color:purple'>abstract</i>&nbsp;";
            if(mods.static) b+="<i style='color:blue'>static</i>&nbsp;  ";
            if(mods.native) b+="<i style='color:green'><b>native<b></i>&nbsp;  ";
            if(mods.transient) b+="<i style='color:pink'>transient</i>&nbsp;  ";
            if(mods.volatile) b+="<i style='color:pink'>volatile</i>&nbsp;  ";

            return b;
        }
    };

    const ColorCode = {
        hash: BS.color.primary,
        sha: BS.color.primary,
        md5: BS.color.primary,
        ascii: BS.color.info,
        key: BS.color.pink,
        rsa: BS.color.pink,
        // invoked dynamically
        id: BS.color.purple,
        // loaded from an external file
        led: BS.color.warning,
        dd: BS.color.warning
    };

    function findColorCode(tagname){
        for(let i in ColorCode) if(tagname.indexOf(i)>-1) return ColorCode[i];
        return null;
    }

    var Render = {
        methodTag: '<span class="badge badge-pill badge-success probe">method</span>',
        fieldTag: '<span class="badge badge-pill badge-primary probe">field</span>',
        classTag: '<span class="badge badge-pill badge-purple probe">class</span>',
        nativeTag: '<span class="badge badge-pill badge-pink probe">native</span>'
    };



    function renderClassDetail( row ) {
        let body = '', color=null;
        if(row.package != null){
            body +=  `<p><b>Package :</b>&nbsp;&nbsp;<a href="${DexcaliburAPI.ui.finderLink("package",row.package.name)}">${row.package.name} (size: ${row.package.size})</a><br><b>Extends :</b>`;
        }else{
            body +=  `<p><b>Package :<b><i>None</i><br><b>Extends :</b>`;

        }

        if(row.supers != null){
            for(let i=0; i<row.supers.length; i++){
                body += (i>0?"&lt;":"")+`&nbsp;
                    <a href='${DexcaliburAPI.ui.finderLink("class",row.supers[i].name)}'>
                    ${(row.supers[i].alias!=null? "<b class='alias-text text-info' >"+DexcaliburAPI.ui.htmlEncode(row.supers[i].alias)+"</b>":"")}
                    &nbsp;${DexcaliburAPI.ui.htmlEncode(row.supers[i].name)}</a>&nbsp;`;
            }
        }else{
            body += "<i>None</i>";
        }

        /*if(row.extends != null){
            body += "&nbsp;<a href='finder.html?class="+btoa(encodeURIComponent(row.extends.name))+"'>"+htmlEncode(row.extends.alias!=null? row.extends.alias : row.extends.name)+"</a>";
         }else{
            body += "None"
        }*/
        
        body += '<br><b>Implements :</b>&nbsp;&nbsp;';
        
        if(row.implements != null){
            //body += "<ul>";
            for(let i=0; i<row.implements.length; i++){
                body += "<a href='finder.html?class="+btoa(encodeURIComponent(row.implements[i]))+"'>"+htmlEncode(row.implements[i])+"</a> <b>/</b> &nbsp;";
            }
            //body += "</ul>"
        }else{
            body += "None"
        }
     
        //body += '<tr>'+
        //    '<td>Implements :</td><td>';
       
/*        for(let i=0; i<row.implements.length; i++){
            body += ((row.implements[i] != null)? row.implements[i].name : 'None')+'<br>';
        }
            
        body += '</td></tr>';
        body += '</table>
        */
        body+= `</p>
            <p>Fields</p>
            <table class="table table-sm">
                <thead><tr>
                    <th scope="col" class="col-sm-2 col-lg-3">Action</th>
                    <th scope="col" class="col-sm-1 col-lg-1">Modifiers</th>
                    <th scope="col" class="col-sm-1 col-lg-1">Type</th>
                    <th scope="col-lg-7">Name</th>
                </thead><tbody>`;
         
        if(row.fields != null){
            for(let i in row.fields){

                //missing = (row.fields[i].tags.indexOf("missing")>-1)? ' style="color:#F00"' : ''; 

                body += '<tr><td>'+
                    //'<td><a  class="badge badge-secondary probe" field="'+btoa(encodeURIComponent(row.fields[i].__signature__))+'">Probe OFF</a>&nbsp;&nbsp;'+
                    //'<a class="badge badge-secondary" onclick="intercept(\''+btoa(encodeURIComponent(row.fields[i].__signature__))+'\')">Intercept</a>'+
                    //'<a class="badge badge-purple getterof" target="about" field="'+btoa(encodeURIComponent(row.fields[i].__signature__))+'">getter</a>&nbsp;'+
                    '<span class="badge badge-pill badge-pink badge-action fieldxref" target="about" field="'+btoa(encodeURIComponent(row.fields[i].__signature__))+'">setters / getters</span></td>'; 
                
                
                if(row.fields[i].modifiers != null) 
                    body += `<td> ${BS.modifiers(row.fields[i].modifiers)}</td>`;
                else
                    body += "<td></td>";
                    
                if(row.fields[i].type != null){
                    body += `<td><a href="${DexcaliburAPI.ui.finderLink("class",row.fields[i].type.name)}">${row.fields[i].type.name} ${row.fields[i].type.arr?"[]":""}</a></td><td>`;
                }else
                    body += `<td></td><td>`;


                if(row.fields[i].alias != null){
                    body += '<b>'+htmlEncode(row.fields[i].alias)+'</b>&nbsp;';
                }

                if(row.fields[i].tags != null && row.fields[i].tags.indexOf("missing")>-1){
                    body += '<a target="about" href="finder.html?field='+btoa(encodeURIComponent(row.fields[i].__signature__))+'" style="color:#F00" >'+htmlEncode(row.fields[i].name); //+" ( "+row.fields[i].__signature__+" )");
                }else{
                    body += '<a target="about" href="finder.html?field='+btoa(encodeURIComponent(row.fields[i].__signature__))+'">'+htmlEncode(row.fields[i].name);
                }
                
                if(row.fields[i].__inherit === true) body += "&nbsp;"+DexcaliburAPI.ui.badge.make('success','inherited');

                body += '</a></td></tr>';
            }
        }

        body+= '</table><p>Methods</p><table class="table table-sm"><thead><tr><th scope="col" class="col-sm-2 col-lg-3">Action</th><th scope="col" class="col-sm-1 col-lg-1">Type</th><th scope="col-lg-8">Name</th></thead><tbody>';
        
         if(row.methods != null){
             for(let i in row.methods){
                 body += '<tr>'+
                    '<td><span  class="badge badge-pill badge-'+(row.methods[i].probing? 'success':'primary')+' probe" meth="'+btoa(encodeURIComponent(row.methods[i].__signature__))+'">Probe '+(row.methods[i].probing? 'ON&nbsp;&nbsp;':'OFF')+'</span>&nbsp;&nbsp;'+
                    //'<a  class="badge badge-danger">Intercept</a>'+
                    '<span class="badge badge-pill badge-purple badge-action xrefto" target="about" meth="'+btoa(encodeURIComponent(row.methods[i].__signature__))+'">xref to</span>&nbsp;'+
                    '<span class="badge badge-pill badge-pink badge-action xreffrom" target="about" meth="'+btoa(encodeURIComponent(row.methods[i].__signature__))+'">xref from</span></td><td>';

                
                if(row.methods[i].modifiers != null) 
                    body += BS.modifiers(row.methods[i].modifiers);
                        
                body += '</td><td><a target="about" href="finder.html?method='+btoa(encodeURIComponent(row.methods[i].__signature__))+'" ';

                if(row.methods[i].__aliasedCallSignature__ != null)
                    body += 'style="color:black;"><b>'+htmlEncode(row.methods[i].__aliasedCallSignature__)+'<b>';
                else
                    body += '>'+htmlEncode(row.methods[i].__callSignature__);

                    body += '</a></td>'+
                 '</tr>';
             }
         }


        
        body += '</tbody></table>';
        return body;
    }

    function renderXrefGraph(treeData){


        var size = {
            height: 500,
            width: 800
        };
        var options = {
            nodeRadius: 4,
            fontSize: 12
        };

        var  maxLabelLength = 50;

        
        var tree = d3.layout
            .tree()
            .sort(null)
            .size([size.height, size.width - maxLabelLength * options.fontSize])
            .children(function(d) {
                return (!d.data || d.data == null || d.data.length === 0) ? null : d.data;
            });
        

        console.log("init OK");
        var nodes = tree.nodes(treeData.data);

        console.log("data OK");
        var links = tree.links(nodes);

        console.log("links OK");
        var layoutRoot = d3
            .select("#d3xref")
            .append('svg:svg')
            .attr('width', size.width)
            .attr('height', size.height)
            .append('svg:g')
            .attr('class', 'container')
            .attr('transform', 'translate(' + maxLabelLength + ',0)');

        // Edges between nodes as a <path class="link" />
        var link = d3.svg.diagonal().projection(function(d) {
            return [d.y, d.x];
        });

        layoutRoot
            .selectAll('path.link')
            .data(links)
            .enter()
            .append('svg:path')     
            .attr('class', 'link')
            .attr('stroke','#ccc')
            .attr('fill','none')
            .attr('d', link);

        /*
            Nodes as
            <g class="node">
                <circle class="node-dot" />
                <text />
            </g>
        */
        var nodeGroup = layoutRoot
            .selectAll('g.node')
            .data(nodes)
            .enter()
            .append('svg:g')
            .attr('class', 'node')
            .attr('transform', function(d) {
                return 'translate(' + d.y + ',' + d.x + ')';
            });

        nodeGroup
            .append('svg:circle')
            .attr('class', 'node-dot')
            .attr('stroke','red')
            .attr('stroke-width','1')
            .attr('fill','lightsalmon')
            .attr('r', options.nodeRadius);

        nodeGroup
            .append('svg:text')
            .attr('text-anchor', function(d) {
                return d.children ? 'end' : 'start';
            })
            .attr('dx', function(d) {
                var gap = 2 * options.nodeRadius;
                return d.children ? -gap : gap;
            })
            .attr('dy', 3) 
            .text(function(d) {
                return d.name;
            });
    }

    function renderCallerDetail( row ) {
        let body = '';

        caller_type = "Class";
        if(row.caller.indexOf("->")>-1)
            caller_type = "Field";
        else if(row.caller.indexOf("(")>-1)
            caller_type = "Method";

        let calleed_type = "Class";
        if(row.callee.indexOf("->")>-1)
            calleed_type = "Field";
        else if(row.callee.indexOf("(")>-1)
            calleed_type = "Method";

        body += '<table class="table table-sm"><thead><tr><th scope="col">Role</th><th scope="col">Action</th><th scope="col">Type</th><th scope="col">Name</th></thead><tbody>';
        body += '<tr><td><b>Caller</b></td><td>';

        if(row.callee.indexOf("(")==-1)
            body += '<a  class="badge badge-secondary">Probe ON'+
                    '</a>&nbsp;&nbsp;<!--<a  class="badge badge-secondary">Intercept ON</a>-->';
        else
            body += '<a  class="badge badge-success probe" meth="'+btoa(encodeURIComponent(row.caller))+'">Probe ON'+
                    '</a>&nbsp;&nbsp;<!--<a  class="badge badge-danger">Intercept</a>-->';
                /*
            body += '<a  class="badge badge-'+(row.methods[i].probing? 'success':'primary')+' probe" meth="'+btoa(row.methods[i].__signature__)+'">Probe '+(row.methods[i].probing? 'ON':'OFF')+
                    '</a>&nbsp;&nbsp;<a  class="badge badge-danger">Intercept</a>';
                */

        body += '<td>'+caller_type+'</td><td><a target="about" href="finder.html?method='+btoa(encodeURIComponent(row.caller))+'">';
        
        //if(row.caller.alias)
        body += htmlEncode(row.caller)+'</a></td></tr><tr><td><b>Callee</b></td><td>';
           

        if(row.callee.indexOf("(")==-1)
            body += '<a  class="badge badge-secondary">Probe ON'+
                    '</a>&nbsp;&nbsp;<!--<a  class="badge badge-secondary">Intercept ON</a>-->';
        else
            body += '<a  class="badge badge-success probe" meth="'+btoa(encodeURIComponent(row.caller))+'">Probe ON'+
                    '</a>&nbsp;&nbsp;<!--<a  class="badge badge-danger">Intercept</a>-->';
                    
        body += '</td><td>'+calleed_type+'</td><td><a target="about" href="finder.html?method='+btoa(encodeURIComponent(row.callee))+'">'+htmlEncode(row.callee)+'</a></td></tr></table>';

//        $.ajax("/api/method/");
        /* body += '<div class="row"><div class="col-lg-2 col-lg-offset-8">See more</div></div>';
        body += '<code>';
            body += "disass";
        body += '</code>'; */
        return body;
    }

    function zeroPaddingNumber( pNumber, pWidth){
        let neg = (pNumber<0);
        let i = pNumber.toString(16);

        if(neg) i = i.substr(1);
        if(i.length%2==1) i='0'+i;
        
        if(i.length/2 < pWidth){
            i = ('00'.repeat(pWidth-(i.length/2)))+i;
        }

        if(neg){
            return `<span style="color:blue">-${i}</span>`;
        }else{
            return `<span style="color:black"> ${i}</span>`;
        }
    }

    // print to hexdump format
    function printByteArray(barray, width){
        let d="<pre>";
        
        for(let i=0; i<barray.length; i++){
            if(i>0 && i%16==0) d+="<br>";

            d+= zeroPaddingNumber( barray[i], width>>3); 
            d+=" "
        } 
        return d+"</pre>";
    }
    
    function renderDatablockDetail( row ) {
        let body = '', d="";

        body += '<table class="table table-sm">';
        body += '<tr><td><b>Location</b></td><td><a href="finder.html?method='+btoa(encodeURIComponent(row.parent))+'">'+htmlEncode(row.parent)+'</a></td></tr>';
        body += '<tr><td><b>Label</b></td><td>'+htmlEncode(row.name)+'</td></tr>';
        body += '<tr><td><b>Size</b></td><td>'+(parseInt(row.length,10)*parseInt(row.width,10))+'&nbsp; bits</td></tr>';
        body += '<tr><td><b>Entry width</b></td><td>'+row.width+'&nbsp; bits</td></tr>';
        body += '</table>';
        
        body += '<table class="table table-sm"><thead><tr><th scope="col" style="width:10em">Tag</th><th scope="col">Data</th></thead><tbody>';
        


        for(let i in row.tags){
            d="";
            body += "<tr><td>"+htmlEncode(row.tags[i])+"</td><td>";
            if(row.tags[i]=="ascii"){
                row.values.map((x)=>{ d+=String.fromCharCode(x)});
            } 
            else{
                d = "0x";
                row.values.map((x)=>{ 
                    d+=x.toString(16) ;
                });
            }

            body += htmlEncode(d);
            body += "</td></tr>";
        }
        body += "<tr><td>raw</td><td>"+printByteArray(row.values,row.width)+"</td></tr>";
         
        body += "</tbody></table>"
        return body;
    }

    function renderMethodDetail( row ) {
        let body = '', j=0, vmParams='';


        let codeID = IdRegister.codeReg.next();
        let codeID_Simple = IdRegister.codeReg.next();

        //body += '<table class="table table-sm"><thead><tr><th scope="col">Role</th><th scope="col">Action</th><th scope="col">Type</th><th scope="col">Name</th></thead><tbody>';
        body += '<table class="table table-sm nestedTable verticalHead">';
        body += '<tr><td class="col-sm-12 col-lg-2"><b>Modifiers</b></td><td class="col-sm-12 col-lg-10">';

        for(let i in row.modifiers){
            if(j==8) body+="<br>";
            if(i != "visibility"){
                body += '&nbsp;<span class="badge badge-pill badge-success">'+i+'</span>';
            }
            j++;
        }

        body += '</td></tr>'; 
        body += '<tr><td>Class</td><td><a href="finder.html?class='+btoa(encodeURIComponent(row.enclosingClass))+'">'+htmlEncode(row.enclosingClass)+'</a></td></tr>';
        body += '<tr><td>Fullname</td><td>'+htmlEncode(row.enclosingClass+'.'+row.name)+'</td></tr>';
        
        if(row.args.length > 0){
            vmParams  += '<i>&nbsp;Parameters :</i>'
        }
        for(let i=0;  i<row.args.length; i++){
            sgt = row.args[i].name;

            vmParams += `<div class="input-group input-group-sm">
                            <div class="input-group-prepend">
                                <span class="input-group-text" style="width:3em">p${i}</span>
                                <span class="input-group-text">
                                    <input type="checkbox" class="simplifyParamNS" editor="${codeID_Simple}" id="${codeID_Simple}-s-p${i}" value="1" checked/>
                                    &nbsp;Not set 
                                </span>
                            </div>
                            <input type="text" id="${codeID_Simple}-v-p${i}" class="form-control" placeholder="${sgt+(row.args[i].arr?"[]":"")}" disabled/>
                        </div>`;


            body += '<tr><td>Arg '+htmlEncode(i)+'</td><td>';
            
            if(row.args[i].primitive===false)
                body += '<a href="finder.html?class='+btoa(encodeURIComponent(sgt))+'">'+htmlEncode(sgt)+'</a>';
            else
                body += htmlEncode(sgt);

            body += '</td></tr>';
        }

        
        body += '<tr><td>Return</td><td><a class="retlink" href="finder.html?class='+btoa(encodeURIComponent(row.ret.name))+'">'+htmlEncode(row.ret.name)+'</td></tr>';
        body += '</table>';

        if(row.modifiers.native==true){
            body += `<div class="alert alert-info border border-info show" role="alert">
                        <p>This function is native.<p>
                    </div>`;
            return body;
        }


        //body += `<div class="btn btn-primary simplify" editor="${codeID}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">Simplify</div>`;

        //body += '<h4>Disassembled bytecode</h4>';
        body += `<ul class="nav">
                    <li class="nav-item">
                        <span class="nav-link smali dxc-active-item" editor="${codeID}" hideeditor="${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">Smali</span>
                    </li>
                    <li class="nav-item">
                        <span class="nav-link simplify dxc-inactive-item" hideeditor="${codeID}" editor="${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">
                            Run smali (VM)
                            <span class="badge badge-pill badge-primary" style="font-size:0.8em">new</span>
                        </span>
                    </li>
                    <li class="nav-item">
                        <span class="nav-link hookhistory dxc-inactive-item" hideeditor="${codeID};${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">
                            Hook history
                            <span class="badge badge-pill badge-primary" style="font-size:0.8em">new</span>
                        </span>
                    </li>
                </ul>`;
        body += '<div id="'+codeID+'"></div>';

        body += `<div id="${codeID_Simple}-view" style="display:none">
                    <div class="row" style="margin:0px">
                        <div class="col-md-8" style="background-color:#272822;margin-right:0px;padding-right:0px;">
                            <div style="width:100%;color:#bbb;background-color:#403127;margin:0px;text-align:right">Configure and click Run -&gt;&nbsp;&nbsp;</div> 
                            <div id="${codeID_Simple}"></div>
                        </div>
                        <div class="col-md-4" style="background-color:#fff;margin:0px;padding:0px;width:33%">
                            <ul class="nav" style="width:100%">
                                <li class="nav-item">
                                    <span class="nav-link dxc-active-item see_params" veditor="${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">
                                        Parameters
                                    </span>
                                </li>
                                <li class="nav-item">
                                    <span class="nav-link dxc-inactive-item see_events" veditor="${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">
                                        Events
                                    </span>
                                </li>
                            </ul>
                            <div id="${codeID_Simple}-params">`;

                        
                body += vmParams;
                                
                                
                body += `
                            <i>&nbsp;Execution settings :</i>   
                            <div class="input-group input-group-sm mb-1 mt-1">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">Callstack max depth (-1 = unlimit)</span>
                                </div>
                                <input type="number" id="${codeID_Simple}-depth" width="5" class="form-control" value="0"/>
                            </div>
                            <i>&nbsp;VM Settings :</i><br>
                            <ul>
                                <li class="nav-item custom-control custom-switch">
                                    <input type="checkbox" id="${codeID_Simple}-clinit" class="custom-control-input" value="1">
                                    <label class="custom-control-label" for="${codeID_Simple}-clinit">Execute &lt;clinit&gt; of parent class</label>     
                                </li>
                            </ul>
                            <div class="row" >
                                    <div class="col-lg-12" style="text-align:center">
                                        <button type="button" class="btn btn-success btn-sm simplifyRun" editor="${codeID_Simple}" method="${encodeURIComponent(btoa(encodeURIComponent(row.__signature__)))}">
                                            <span class="fa fa-play">&nbsp;</span>
                                            Run    
                                        </button>
                                    </div>
                                </div> 
                            </div>
                        <div id="${codeID_Simple}-events" style="display:none">
                            <i>Logs</i>
                        </div>
                    </div>
                </div>`;
        //body += '<div id="'+codeID_Simple+'" style="display:none"></div>';

        
        $.ajax(
            "../api/method/disass/"+encodeURIComponent(btoa(encodeURIComponent(row.__signature__))),
            {
                method: "get",
                statusCode: {
                    200: function(data){
                        data = JSON.parse(data);
                        let code = $("#"+codeID);
                        let codeBody = "";
                        console.log(data,code);
                        for(let i=0; i<data.disass.length; i++){
                            codeBody += "\n";
                            if(data.disass[i].tag!=null){
                                codeBody += "."+data.disass[i].tag.substr(1)+"\n";
                            }
                            if(data.disass[i].instr.length>0){
                                //console.log(data.disass[i].instr);
                                for(let j=0; j<data.disass[i].instr.length; j++){
                                    if(data.disass[i].instr[j].value == null){
                                        console.log("Instr is null : <"+i+","+j+">");
                                    }else{
                                        if(data.disass[i].instr[j].value.indexOf("move-result-object")==0)
                                            codeBody += "\t"+data.disass[i].instr[j].value+"\n";
                                        else    
                                            codeBody += DexcaliburAPI.ui.htmlEncode(data.disass[i].instr[j].value)+"\n";
                                    }
                                }   
                            }
                        }
                        code.html(codeBody);
                        //code.html("var a=new String('test');");
                        setupAceEditor(codeID);
                    }
                }
            }
        );
        return body;
    }



    $(document).ready(function() {

        $.ajax(
            "../api/tags",
            {
                method:"get",
                statusCode: {
                    200: function(data){
                        let tags = JSON.parse(data), cc=null;
                        for(let i=0; i<tags.length;i++){
                            cc = findColorCode(tags[i]);
                            if(cc==null) console.log("Need more color code"); 
                            for(let j=0; j<tags[i].length;j++){
                                ApplicationMap.tags.push(tags[i][j]) = tags[i];
                            }
                        }
                    }
                }
            }
        );
       

        let clsTable = $('#dataTables-finder').DataTable({
            searching: false,
            paging: false,
            columns: [
                {
                    "className":      'details-control',
                    "orderable":      false,
                    "data":           null,
                    "defaultContent": ''
                },
                {  "defaultContent": '' },
                {  "defaultContent": '' },
                { 
                    render: function(data, type, row, meta ){
                        if(row.name != null)
                            return '<span  class="badge badge-pill badge-success badge-action  probe" meth="'+btoa(encodeURIComponent(row.name))+'">ON</span>';
                        else    
                            return '';
                    }
                }
            ],
            responsive: true
        });

        let gsetterTable = $('#dataTables-gsetter').DataTable({
            searching: false,
            paging: false,
            columns: [{
                    className:  'col-md-1 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        if(row.t=='s')
                            return BS.badge("purple","set");
                        else
                            return BS.badge("pink","get");
                    }
                },
                {  
                    // render called/caller name
                    className:  'col-md-6 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        //console.log("xref :",row);
                        let t = '<a target="about" href="finder.html?method='+btoa(encodeURIComponent(row.s))+'">';  

                        // alias
                        if(row.a != null)
                            return t+htmlEncode(row.a)+'</a><br><i>'+htmlEncode(row.s)+'</i>';
                        else
                            return t+htmlEncode(row.s)+'</a>';

//                        return '<a target="about" href="finder.html?method='+btoa(encodeURIComponent(row.s))+'">'+htmlEncode(row.s)+'</a>';                            
                    }
                 },
                {  
                    // render tags

                    className:  'col-md-3 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        let t = "";
                        if(row.tags==null) return t;
                        for(let i=0; i<row.tags.length; i++){
                            switch(row.tags[i]){
                                case "di":
                                    t += '&nbsp;<span class="badge badge-pill badge-success">internal</span>'
                                    break;
                                case "dd":
                                    t += '&nbsp;<span class="badge badge-pill badge-purple">dynamic</span>'
                                    break;
                                case "id":
                                    t += '&nbsp;<span class="badge badge-pill badge-purple">invoked</span>'
                                    break;
                            }
                        }
                        return t;
                    }},
                { 
                    // render probing btn
                    
                    className:  'col-md-2 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        if(row.s.indexOf("<clinit>")>-1)
                            return ''; //<a class="badge badge-secondary" tip="Class init cannot be hooked">Probe</a>';
                        else
                            return '<span  class="badge badge-pill badge-'+(row.probing? 'success':'primary')+' badge-action probe" meth="'+btoa(encodeURIComponent(row.s))+'">Probe '+(row.probing? 'ON&nbsp;&nbsp;':'OFF')+'</span>';
                    }
                }
            ],
            responsive: true
        });

        let xrefTable = $('#dataTables-xref').DataTable({
            searching: false,
            paging: false,
            columns: [{

                    "className":      'col-md-1',
                    render: function(data, type, row, meta ){
                        if(row.t != null){
                            console.log(row);
                            if(row.t=='f')
                                return 'Field';
                            else if(row.t=='m')
                                return 'Method';                            
                            else
                                return 'Class';
                        }else{
                            return 'Method';
                        }
                    }
                },
                {  
                    // render called/caller name
                    "className":      'col-md-6 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        //console.log("xref :",row);
                        let t = null
                        if(row.t != null){

                            // begin of the link
                            if(row.t=='f')
                                t = '<a target="about" class="dxc-wrapped-row" href="finder.html?field='+btoa(encodeURIComponent(row.s))+'">';
                            else if(row.t=='m')
                                t = '<a target="about" class="dxc-wrapped-row" href="finder.html?method='+btoa(encodeURIComponent(row.s))+'">';                            
                            else
                                t = '<a target="about" class="dxc-wrapped-row" href="finder.html?class='+btoa(encodeURIComponent(row.s))+'">';

                            // alias
                            if(row.a != null)
                                return t+htmlEncode(row.a)+'</a><br><i>'+htmlEncode(row.s)+'</i>';
                            else
                                return t+htmlEncode(row.s)+'</a>';
                            
                        }else{
                            console.log("Else case trigged");
                            let t = '<a target="about" class="dxc-wrapped-row" href="finder.html?method='+btoa(encodeURIComponent(row.s))+'">';
                            if(row.a != null)
                                return t+htmlEncode(row.a)+'</a><br><i>'+htmlEncode(row.s)+'</i>';
                            else
                                return t+htmlEncode(row.s)+'</a>';
                        }

                    }
                 },
                {  
                    // render tags
                    "className":      'col-md-3 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        let t = "";
                        if(row.tags==null) return t;
                        for(let i=0; i<row.tags.length; i++){
                            switch(row.tags[i]){
                                case "di":
                                    t += '&nbsp;<span class="badge badge-pill badge-success">internal</span>'
                                    break;
                                case "dd":
                                    t += '&nbsp;<span class="badge badge-pill badge-purple">dynamic</span>'
                                    break;
                                case "id":
                                    t += '&nbsp;<span class="badge badge-pill badge-purple">invoked</span>'
                                    break;
                            }
                        }
                        return t;
                    }},
                { 
                    // render probing btn
                    "className":      'col-md-2 dxc-wrapped-row',
                    render: function(data, type, row, meta ){
                        if(row.s.indexOf("<clinit>")>-1 || (row.t!=null && row.t=='f'))
                            return ''; //<a class="badge badge-secondary" tip="Class init cannot be hooked">Probe</a>';
                        else
                            return '<span  class="badge badge-pill badge-'+(row.probing? 'success':'primary')+' badge-action  probe" meth="'+btoa(encodeURIComponent(row.s))+'">Probe '+(row.probing? 'ON&nbsp;&nbsp;':'OFF')+'</span>';
                    }
                }
            ],
            responsive: true
        });

        function renderXrefModal( ref, from ) {
            let body = '', j=0;

            if(from)
                $('#xrefModalLabel').html("<span class='title'>XRef from </span><h4 class='symbol dxc-wrapped-row'>"+htmlEncode(decodeURIComponent(atob(ref)))+"</h4>");
            else
                $('#xrefModalLabel').html("<span class='title'>XRef to</span><h4 class='symbol dxc-wrapped-row'>"+htmlEncode(decodeURIComponent(atob(ref)))+"</h4>");

            
            xrefTable.clear();
            xrefTable.draw();   
            $.ajax(
                "../api/method/xref/"+ref,
                {
                    method: "get",
                    data: {
                        type: (from ? "from":"to")
                    },
                    statusCode: {
                        200: function(data){
                            xrefTable.clear();
                            xrefTable.rows.add(JSON.parse(data).data);
                            xrefTable.draw();
                        },
                        404: function(data){
                            alert("Error : "+JSON.parse(data).err);
                            console.log(data);
                        },
                        500: function(data){
                            alert("Fatal error : "+JSON.parse(data).err);
                            console.log(data);
                        }
                    }
                }
            );

            $("#xrefModal").modal();
            return true;
        }

        function renderGsetterModal( ref) {
            let body = '', j=0;

            $('#gsetterModalLabel').html("<span class='title'>Setters & getters of </span><h4 class='symbol dxc-wrapped-row'>"+htmlEncode(decodeURIComponent(atob(ref)))+"</h4>");
  
            gsetterTable.clear();
            gsetterTable.draw();   
            $.ajax(
                "../api/field/xref/"+ref,
                {
                    data:{  
                        _t: (new Date()).getTime()
                    },
                    method: "get",
                    statusCode: {
                        200: function(data){
                            gsetterTable.clear();
                            gsetterTable.rows.add(JSON.parse(data).data);
                            gsetterTable.draw();
                        },
                        404: function(data){
                            alert("Error : "+JSON.parse(data).err);
                            console.log(data);
                        },
                        500: function(data){
                            alert("Fatal error : "+JSON.parse(data).err);
                            console.log(data);
                        }
                    }
                }
            );

            $("#gsetterModal").modal();
            return true;
        }

        function renderClassTable(table){
            $("#finder-col1").html("");
            $("#finder-col2").html("Package");
            $("#finder-col3").html("Name");
            $("#finder-col4").html("Action");

            table.destroy();
            return $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'col-md-1 details-control',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": ''
                    },
                    {  

                        "className":      'col-md-4 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            //console.log(data, type, row, meta);
                            return row.package.name;
                        }
                    },
                    {   
                        "className":      'col-md-5 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            let color = (row.tags.indexOf("missing")>-1)? ' style="color:#F00"' : ''; 
                            
                            let b = "";
                            if(row.alias != null){
                                b = '<span  class="dxc-wrapped-row"><b '+color+'>'+htmlEncode(row.alias)+'</b>&nbsp;<i class="secondary-text">'+htmlEncode(row.name)+'</i></span>';
                            }
                            else if(row.name != null){
                                if(row.name.lastIndexOf("$")>row.name.lastIndexOf('.')){
                                    b = '<span  class="dxc-wrapped-row" '+color+'>'+row.name.substr(row.name.lastIndexOf('.')+1)+'</span>';
                                }else{
                                    b = '<span  class="dxc-wrapped-row" '+color+'>'+row.simpleName+'</span>';
                                }
                            }else{
                                console.log("Unable to render Class : "+row);
                            }

                            // loaded from an external dex file
                            if(row.tags.indexOf("di") > -1){
                                b += BS.badge("success", "internal");
                            }
                            if(row.tags.indexOf("led") > -1){
                                b += BS.badge(
                                        findColorCode("led")
                                        , "external");
                            }
                            if(row.tags.indexOf("dd") > -1){
                                b += BS.badge(
                                        findColorCode("dd")
                                        , "D-dynamic");
                            }

                            return b;
                            /*
                            if(row.enclosingClass != undefined)
                                return row.enclosingClass.simpleName+"$"+row.simpleName;
                            else{
                                return row.simpleName;
                            }*/
                        }
                    },
                    { 
                        "className":      'col-md-2',
                        render: function(data, type, row, meta ){
                            let b='<span  class="badge badge-pill badge-info badge-action rename" ename="'+btoa(encodeURIComponent(row.name))+'" subt="class" subject="'+btoa(encodeURIComponent(row.name))+'">Rename</span>';

                            return b;
                        }
                    }
                ],
                responsive: true
            });
        }

        function renderMethodTable(table){
            $("#finder-col1").html("");
            $("#finder-col2").html("Class");
            $("#finder-col3").html("Method");
            $("#finder-col4").html("Action");

            table.destroy();
            return $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'col-md-1 details-control',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": ''
                    },
                    { 
                        "className":      'col-md-3 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            return ((row.enclosingClass!=null)? htmlEncode(row.enclosingClass) : '[Missing]');
                        }
                    },
                    {  
                        "className":      'col-md-6 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            let color = (row.tags.indexOf("missing")>-1)? ' style="color:#F00"' : ''; 
                            let b= '<span  class="dxc-wrapped-row" meth="'+btoa(encodeURIComponent(row.__signature__))+'"'+color+' >'+(row.alias!=null? '<b>'+htmlEncode(row.alias)+'</b><br>&nbsp;<i class="secondary-text">'+htmlEncode(row.__signature__)+'</i>':'&nbsp;'+htmlEncode(row.__callSignature__))+'</span>';
                            
                            if(row.tags.indexOf("dd") > -1){
                                b += BS.badge(
                                        findColorCode("dd")
                                        , "D-dynamic");
                            }
                            return b;
                        }
                    },
                    { 
                        
                        "className":      'col-md-3',
                        render: function(data, type, row, meta ){
                            //console.log(row.__signature__);
                            let b='<span  class="badge badge-pill badge-primary badge-action probe" meth="'+btoa(encodeURIComponent(row.__signature__))+'">Probe</span>&nbsp;';
                            // b += '&nbsp;<a  class="badge badge-secondary cfg" meth="'+btoa(encodeURIComponent(row.__signature__))+'">Call Graph</a>&nbsp;';
                            // b += '&nbsp;<a  class="badge badge-secondary seemore" meth="'+btoa(encodeURIComponent(row.__signature__))+'">See more</a>';
                            b += '<span  class="badge badge-pill badge-info badge-action rename" ename="'+btoa(encodeURIComponent(row.alias!=null? row.alias : row.name))+'" subt="meth" subject="'+btoa(encodeURIComponent(row.__signature__))+'">Rename</span>';
                            b += '&nbsp;<span  class="badge badge-pill badge-purple badge-action xrefto" meth="'+btoa(encodeURIComponent(row.__signature__))+'">xref to</span>';
                            b += '&nbsp;<span  class="badge badge-pill badge-pink badge-action xreffrom" meth="'+btoa(encodeURIComponent(row.__signature__))+'">xref from</span>';
                            b += '&nbsp;<span  class="badge badge-pill badge-warning badge-action seegraph" meth="'+btoa(encodeURIComponent(row.__signature__))+'">Xgraph</span>';

                            return b;
                            /*
                            if(row.enclosingClass != undefined)
                                return row.enclosingClass.simpleName+"$"+row.simpleName;
                            else{
                                return row.simpleName;
                            }*/
                        }
                    }
                ],
                responsive: true
            });
        }

        function renderFieldTable(table){
            $("#finder-col1").html("");
            $("#finder-col2").html("Class");
            $("#finder-col3").html("Field");
            $("#finder-col4").html("Action");

            table.destroy();
            return $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'col-md-1 details-control',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": ''
                    },
                    { 
                        "className":      'col-md-3 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            if(row.enclosingClass!=null){
                                return "<a href='finder.html?class="+btoa(encodeURIComponent(row.enclosingClass.name))+"'>"+(row.enclosingClass.alias!=null? "<b class='alias-text' >"+htmlEncode(row.enclosingClass.alias)+"</b>" : "")+"&nbsp;"+htmlEncode(row.enclosingClass.name)+"</a>";
                            }else
                                return '[Missing]';
                        }
                    },
                    {  
                        "className":      'col-md-6 dxc-wrapped-row',
                        render: function(data, type, row, meta ){

                            let color = (row.tags.indexOf("missing")>-1)? ' style="color:#F00"' : ''; 
                            let b = '<span  class="dxc-wrapped-row" '+color+'>'+((row.alias!=null? '<b>'+htmlEncode(row.alias)+'</b>&nbsp;':'&nbsp;')+htmlEncode(row.name));
                            if(row.tags.indexOf("di")>0) b += BS.badge('success','internal');
                            //if(row.modifiers.static==true) b += BS.badge('danger','static');

                            return b+'</span>';
                        }
                    },
                    {   
                        "className":      'col-md-2 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            let b='<span  class="badge badge-pill badge-info badge-action  rename" ename="'+btoa(encodeURIComponent(row.name))+'" subt="field" subject="'+btoa(encodeURIComponent(row.__signature__))+'">Rename</span>&nbsp;';
                            b+='<span class="badge badge-pill badge-pink badge-action fieldxref" target="about" field="'+btoa(encodeURIComponent(row.__signature__))+'">setters / getters</span>';
                            return b;
                        }
                    }
                ],
                responsive: true
            });
        }

        function renderCallerTable(table){
            $("#finder-col1").html("");
            $("#finder-col2").html("Caller");
            $("#finder-col3").html("Callee");
            //$("#finder-col4").html("Action");
            $("#finder-col4").css("display","none");

            table.destroy();
            return $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'col-md-1 details-control',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": ''
                    },
                    { 

                        "className":      'col-md-5 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            return (row.caller!=null)? htmlEncode(row.caller) : '[Missing]';
                        }
                    },
                    {  
                        "className":      'col-md-5 dxc-wrapped-row',
                        render: function(data, type, row, meta ){
                            if(row.callee !== undefined){
                                let txt = ''
                                if(row.callee.indexOf('(')>-1){
                                    txt +=  Render.methodTag;
                                }else if(row.callee.indexOf('->')>-1){
                                    txt +=  Render.fieldTag;
                                    if(row.instr=="SETTER")
                                        txt += BS.badge("purple","set");
                                    else
                                        txt += BS.badge("pink","get");
                                }else{
                                    txt +=  Render.classTag;
                                }
                                return '<span class="dxc-wrapped-row">'+txt+"&nbsp;"+htmlEncode(row.callee)+'</span>';

                            }else
                                return '';
                        }
                    },
                    { 
                        "className":      'col-md-1',
                        "defaultContent": ''
                    }
                ],
                responsive: true
            });
        }

        function renderValuesTable(table){
            $("#finder-col1").html("");
            //$("#finder-col1").addClass("col-md-1");
            $("#finder-col2").html("Value");
            //$("#finder-col2").addClass("col-md-5");
            $("#finder-col3").html("Caller");
            //$("#finder-col3").addClass("col-md-5");
            $("#finder-col4").html("");//style("display","none");
            //$("#finder-col4").addClass("col-md-1");

            table.destroy();
            let t= $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'col-md-1',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": '',
                        "width":"5%"
                    },
                    { 
                        "className":      'col-md-5',
                        render: function(data, type, row, meta ){
                            console.log(row.tags);

                            let b="";

                            if(row.value.length > 60){

                                for(let i=0; i<row.value.length/60; i++){
                                    b += htmlEncode(row.value.substr(i*60,60))+"<br>";
                                }
                                
                            }else{
                                b = htmlEncode(row.value);
                            }

                            if(row.tags.indexOf("dd") > -1){
                                    b += BS.badge(
                                            findColorCode("dd")
                                            , "D-dynamic");
                                }

                                return b ;
                        },
                        "width":"40%"
                    },
                    {  
                        "className":      'col-md-5',
                        render: function(data, type, row, meta ){
                            return '<a target="about" class="dxc-wrapped-row"x href="finder.html?method='+btoa(encodeURIComponent(row.instr.method))+'">'+htmlEncode(row.instr.method)+'</a>';
                        },
                        "width":"40%"
                    },
                    {
                        "className":      'col-md-1',
                         render: function(data, type, row, meta ){
                            return '<span  class="badge badge-pill badge-success badge-action  probe" meth="'+btoa(encodeURIComponent(row.instr.method))+'">Probe</span>&nbsp;';
                         },
                        "width":"15%"

                    }
                ],
                responsive: false
            });
            t.columns.adjust();
            return t;
        }

        
        function renderDatablockTable(table){
            $("#finder-col1").html("");
            $("#finder-col2").html("Position");
            $("#finder-col3").html("Tags");
            $("#finder-col4").html("Action");

            table.destroy();
            return $('#dataTables-finder').DataTable({
                searching: false,
                paging: false,
                columns: [
                    {
                        "className":      'details-control',
                        "orderable":      false,
                        "data":           null,
                        "defaultContent": ''
                    },
                    { 
                        render: function(data, type, row, meta ){
                            return ((row.uid!=null)? htmlEncode(row.uid) : '[Missing]')+" <i style='color:blue'>("+((row.length*row.width)/8)+" bytes)</i>"
                        }
                    },
                    {  
                        render: function(data, type, row, meta ){
                            let r="";
                            if(row.tags!=null){
                                for(let i=0; i<row.tags.length; i++){
                                    r += BS.badge(
                                        findColorCode(row.tags[i])
                                        , row.tags[i]);
                                }
                            }
                            return r;
                        }
                    },
                    { 
                        
                        render: function(data, type, row, meta ){
                            console.log(row);
                            if(row.uid.indexOf("<clinit>")>-1)
                                return '<span class="badge badge-pill badge-secondary" tip="Class init cannot be hooked">Probe</span>';
                            else
                                return '<span  class="badge badge-pill badge-info badge-action probe" meth="'+btoa(encodeURIComponent(row.parent))+'">Probe</span>';
                        }
                    }
                ],
                responsive: true
            });
        }

        function renderBodyTable(data){
            
            //console.log(typeof data, data instanceof Array, data instanceof Object);
            
            if((data instanceof Array)==false)
                data = [data];

                console.log(data);
            
                
            clsTable.clear();

            if(data[0].package !== undefined){
                clsTable = renderClassTable(clsTable);
            }
            else if(data[0].args !== undefined){
                clsTable = renderMethodTable(clsTable);
            }
            else if(data[0].type !== undefined){
                clsTable = renderFieldTable(clsTable);
            }
            else if(data[0].caller !== undefined){
                clsTable = renderCallerTable(clsTable);
            }
            else if(data[0].value !== undefined){ 
                clsTable = renderValuesTable(clsTable);
            }
            else if(data[0].width !== undefined){
                clsTable = renderDatablockTable(clsTable);
            }

            //clsTable.clear();
            clsTable.rows.add(data);
            clsTable.draw();
        }

        htmlEncode = function(txt){
            return $("<div />").text(txt).html();
        }

        // ---------------- SEARCH --------------------------------


        $("#search_request").keypress( function (e) {
            var key = e.which || e.keyCode;
            if (key === 13) {
                $("#button_search").trigger('click');
            }   
        });

        // ---------------- REQUEST HELPER : START ----------------

        var RHelper = new RequestHelper($, "request-helper-view");
        RHelper.onExecute(function(pCmd){
            $("#search_request")[0].value = pCmd;
            $("#button_search").trigger("click");
        });

        $(".prefilter-more").click(function(e){
            if($("#request-helper").css("display")=="block") return;
            $("#request-helper").css("display","block");
            RHelper.init();
            RHelper.render();
        });

        $("#request-helper-view-reset").click(function(e){
            RHelper.reset();
            RHelper.init();
            RHelper.render();
        });      
        $("#request-helper-view-cancel").click(function(e){
            $("#request-helper").css("display","none");
            RHelper.reset();
        });

        // ---------------- REQUEST HELPER : END ------------------

        $('#dataTables-finder tbody').on('click', 'span.simplify', function (e) {
            let codeID = e.currentTarget.getAttribute('editor');
            let hide_codeID = e.currentTarget.getAttribute('hideeditor');
            let method = e.currentTarget.getAttribute('method');


            $('#'+hide_codeID).css('display','none');
            $('#'+codeID+'-view').css('display','block');
            $('#'+codeID).css('display','block');

            $('span.nav-link[editor='+hide_codeID+']').removeClass("dxc-active-item");
            $('span.nav-link[editor='+hide_codeID+']').addClass("dxc-inactive-item");

            $('span.nav-link[editor='+codeID+']').removeClass("dxc-inactive-item");
            $('span.nav-link[editor='+codeID+']').addClass("dxc-active-item");

            //$('button.simplifyRun[editor='+codeID+']').trigger('click');
        });

        $('#dataTables-finder tbody').on('click', 'button.simplifyRun', function (e) {
            let codeID = e.currentTarget.getAttribute('editor');
            let method = e.currentTarget.getAttribute('method');
            let l = (codeID+"-s-").length;

            let reqData = {
                level:0,
                params: {},
                depth: parseInt($("#"+codeID+"-depth").val(),10),
                clinit: $("#"+codeID+"-clinit")[0].checked
            };

            $("input[id^="+codeID+"-s-]").each((i,e)=>{
                reqData.params[e.id.substr(l)] = {notset: e.checked };
            }); 

            $("input[id^="+codeID+"-v-]").each((i,e)=>{
                if(reqData.params[e.id.substr(l)].notset==false)
                    reqData.params[e.id.substr(l)].val = e.value ;
            }); 

            
            $.ajax(
                "../api/method/simplify/"+method,
                {
                    method: "post",
                    contentType: 'application/json',
                    dataType: "json",
                    data: JSON.stringify(reqData),
                    statusCode: {
                        200: function(data){
                            //data = JSON.parse(data);
                            let codeBody = "";
                            for(let i=0; i<data.instr.length; i++){
                                codeBody += data    .instr[i]+"\n";
                            }

                            setupAceEditor(codeID);
                            changeAceLanguage(codeID, "java");
                            changeAceEditor(codeID, codeBody);

                            if(data.logs.length > 0){
                                for(let i=0; i<data.logs.length; i++){
                                    $("#"+codeID+"-events").append("[ANDROID::LOG] "+data.logs[i]);
                                }
                            }
                        }
                    }
                }
            );
        });

        // Enable/disable param value input when not set is checked/unchecked 
        $('#dataTables-finder tbody').on('change','input.simplifyParamNS', function(e){
            let codeID = e.currentTarget.getAttribute('editor');
            let l = codeID.length+3;

            $("input[id^="+codeID+"-v-"+e.currentTarget.id.substr(l)+"]").each((i,a)=>{
                if(e.currentTarget.checked)
                    a.disabled = true;
                else
                    a.disabled = false;
            });
        });

        $('#dataTables-finder tbody').on('click', 'span.see_params', function(e){
            let codeID = e.currentTarget.getAttribute('veditor');


            $('span.see_events[veditor='+codeID+']').removeClass("dxc-active-item");
            $('span.see_events[veditor='+codeID+']').addClass("dxc-inactive-item");

            $('span.see_params[veditor='+codeID+']').removeClass("dxc-inactive-item");
            $('span.see_params[veditor='+codeID+']').addClass("dxc-active-item");

            $("#"+codeID+"-events").css('display','none');
            $("#"+codeID+"-params").css('display','block');
        });


        $('#dataTables-finder tbody').on('click', 'span.see_events', function(e){
            let codeID = e.currentTarget.getAttribute('veditor');

            $('span.see_params[veditor='+codeID+']').removeClass("dxc-active-item");
            $('span.see_params[veditor='+codeID+']').addClass("dxc-inactive-item");

            $('span.see_events[veditor='+codeID+']').removeClass("dxc-inactive-item");
            $('span.see_events[veditor='+codeID+']').addClass("dxc-active-item");

            $("#"+codeID+"-params").css('display','none');
            $("#"+codeID+"-events").css('display','block');
        });

        $('#dataTables-finder tbody').on('click', 'span.smali', function (e) {
            let codeID = e.currentTarget.getAttribute('editor');
            let hide_codeID = e.currentTarget.getAttribute('hideeditor');
            let method = e.currentTarget.getAttribute('method');

            //console.log(codeID,method);
            $.ajax(
            "../api/method/disass/"+method,
            {
                method: "get",
                statusCode: {
                    200: function(data){
                        data = JSON.parse(data);
                        let code = $("#"+codeID);
                        let codeBody = "";
                        //console.log(data,code);
                        for(let i=0; i<data.disass.length; i++){
                            codeBody += "\n";
                            if(data.disass[i].tag!=null){
                                codeBody += "."+data.disass[i].tag.substr(1)+"\n";
                            }
                            if(data.disass[i].instr.length>0){
                                //console.log(data.disass[i].instr);
                                for(let j=0; j<data.disass[i].instr.length; j++){
                                    if(data.disass[i].instr[j].value == null){
                                        console.log("Instr is null : <"+i+","+j+">");
                                    }else{
                                        if(data.disass[i].instr[j].value.indexOf("move-result-object")==0)
                                            codeBody += "\t"+data.disass[i].instr[j].value+"\n";
                                        else    
                                            codeBody += data.disass[i].instr[j].value+"\n"; //DexcaliburAPI.ui.htmlEncode(data.disass[i].instr[j].value)+"\n";
                                    }
                                }   
                            }
                        }
                        //code.html(codeBody);

                        $('#'+hide_codeID+'-view').css('display','none');
                        $('#'+hide_codeID).css('display','none');
                        $('#'+codeID).css('display','block');

                        setupAceEditor(codeID);
                        changeAceLanguage(codeID, "smali");
                        changeAceEditor(codeID, codeBody);

                        $('span.nav-link[editor='+hide_codeID+']').removeClass("dxc-active-item");
                        $('span.nav-link[editor='+hide_codeID+']').addClass("dxc-inactive-item");

                        $('span.nav-link[editor='+codeID+']').removeClass("dxc-inactive-item");
                        $('span.nav-link[editor='+codeID+']').addClass("dxc-active-item");

                        //code.html("var a=new String('test');");
                        //setupAceEditor(codeID);
                    }
                }
            }
        );

            $.ajax(
                "../api/method/disass/"+method,
                {
                    method: "get",
                    data: {
                        level:1
                    },
                    statusCode: {
                        200: function(data){
                            data = JSON.parse(data);
                            let codeBody = "";
                            for(let i=0; i<data.instr.length; i++){
                                codeBody += data    .instr[i]+"\n";
                            }
                            //code.html(codeBody);
                            $('#'+hide_codeID).css('display','none');
                            $('#'+codeID).css('display','block');

                            setupAceEditor(codeID);
                            changeAceLanguage(codeID, "java");
                            changeAceEditor(codeID, codeBody);

                            $('span.nav-link[editor='+hide_codeID+']').removeClass("dxc-active-item");
                            $('span.nav-link[editor='+hide_codeID+']').addClass("dxc-inactive-item");

                            $('span.nav-link[editor='+codeID+']').removeClass("dxc-inactive-item");
                            $('span.nav-link[editor='+codeID+']').addClass("dxc-active-item");

                        }
                    }
                }
            );
        });

        //$('#probelogs').
        $('#dataTables-finder tbody').on('click', 'td.details-control', function () {
            var tr = $(this).closest('tr');
            var row = clsTable.row( tr );
            //console.log(row.child);

            if ( row.child.isShown() ) {
                // This row is already open - close it
                row.child.hide();
                tr.removeClass('shown');
                //tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
            }
            else {
                // Open this row
                let rd = row.data();
                if(rd.package != null){
                    row.child( renderClassDetail(row.data()) ).show();
                    tr.addClass('shown');
                    tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
                }
                else if(rd.args != null){
                    row.child( renderMethodDetail(row.data()) ).show();
                    tr.addClass('shown');
                tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
                }
                else if(rd.type != null){
                    //row.child( renderFieldDetail(row.data()) ).show();
                    //tr.addClass('shown');
                }
                else if(rd.caller != null){
                    row.child( renderCallerDetail(row.data()) ).show();
                    tr.addClass('shown');
                tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
                }
                else if(rd.value != null){
                    row.child( renderStringDetail(row.data()) ).show();
                    tr.addClass('shown');
                tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
                }
                else if(rd.values != null){
                    row.child( renderDatablockDetail(row.data()) ).show();
                    tr.addClass('shown');
                tr[0].nextElementSibling.childNodes[0].className = 'dxc-expandedrow-bg';
                }

            }
        } );

        
        $(document).on("click",".probe",function(){
            let DOM_PROBE =$(this);
            let meth = $(this).attr("meth");

            // DexcaliburAPI.hook.newFutureHook();
            // $("#newHookModal").modal();

            $.ajax('../api/probe/'+meth,{
                method: 'post',
                statusCode: {
                    200: function(data, err){

                        //console.log(DOM_PROBE,hasClass("badge-primary"));
                        if(JSON.parse(data).enable){
                            if(DOM_PROBE.hasClass("badge-primary"))
                                DOM_PROBE.removeClass("badge-primary");

                            DOM_PROBE.addClass("badge-success");
                            DOM_PROBE.text("Probe ON").html();
                        }else{

                            if(DOM_PROBE.hasClass("badge-success"))
                                DOM_PROBE.removeClass("badge-success");

                            DOM_PROBE.addClass("badge-primary");
                            DOM_PROBE.text("Probe OFF").html();
                        }
                    },
                    404: function(){
                        //alert("Failed to add probe (see logs)")
                    }
                }
            })
        });


        $(document).on("click",".xreffrom",function(e){
            let DOM_PROBE =$(this);
            let meth = $(this).attr("meth");

            renderXrefModal(meth,true);
        });
        $(document).on("click",".xrefto",function(e){
            let DOM_PROBE =$(this);
            let meth = $(this).attr("meth");

            renderXrefModal(meth,false);
        });



        $(document).on("click",".fieldxref",function(e){
            //let DOM_PROBE =$(this);
            let field = $(this).attr("field");

            renderGsetterModal(field);
        });

        $(document).on("click",".seegraph",function(e){
            let meth = $(this).attr("meth");

            window.open("/pages/graph_d3.html?type=cgfrom&meth="+meth);
        });

        var GLOBAL = {
            results: null
        };

        $("#button_search").click(function(){
            let val = $("#search_request")[0].value;
            
            json = JSON.stringify({ search: val });

            $.ajax('../api/finder',{
                method: 'get',
                data: {
                    search: encodeURIComponent(btoa(encodeURIComponent(val))),
                    _t: (new Date()).getTime()
                },
                statusCode: {
                    200: function(data){
                        data = JSON.parse(data);
                        //console.log(data);
                        //$("#probelogs").html("");
                        //renderHeaderTable(data.data);
                        if(data.data == null || data.data.length==0){
                            alert("No matches found !");
                        }else{
                            GLOBAL.results = data.data;
                            console.log(data.data);
                            renderBodyTable(data.data);

                            // auto expand, il single row 
                            if(data.data.length == undefined)/*g_search_type === SEARCH.SINGLE)*/{
                                $('#dataTables-finder td.details-control').trigger('click');
                            }

                            $(".pre-request").css("display","none");
                            $(".pre-filter").css("display","block");
                        }

                    },
                    404: function(data){
                        alert("No matches found !");
                        //console.log(data);
                        //alert("Failed to add probe (see logs)")
                    }
                }
            })
        });


        //dmTable.ajax.url("../api/device").load();
        $('#dm-refresh-btn').click(()=>{
            clsTable.ajax.reload();
        });


        // predefine filter event
        $('.pre-request .prefilter').click(function(elem){
            let filt = $(this).attr("prefilt"), token="", dot="";

            if(filt.indexOf("@@")>-1){
                token = prompt("Type the value for the filter :");
                if(token == null) return;
                
                filt = filt.replace("@@",token);
            }

            if($("#search_request")[0].value.length > 0)
                dot = ".";

            if("before"!=$(this).attr("when"))
                $("#search_request")[0].value = $("#search_request")[0].value+dot+filt;
            else
                $("#search_request")[0].value = filt+dot+$("#search_request")[0].value;

            $("#button_search").trigger("click");
            $(".pre-request").css("display","none");
            $(".pre-filter").css("display","block");
        });

        $('.pre-filter .prefilter').click(function(elem){
            let filt = $(this).attr("prefilt"), token="", dot="";

            if(filt.indexOf("@@")>-1){
                token = prompt("Type the value for the filter :");
                filt = filt.replace("@@",token);
            }

            if($("#search_request")[0].value.length > 0)
                dot = ".";

            if("before"!=$(this).attr("when"))
                $("#search_request")[0].value = $("#search_request")[0].value+dot+filt;
            else
                $("#search_request")[0].value = filt+dot+$("#search_request")[0].value;

            $("#button_search").trigger("click");
        });

        $('.prefilter-clean').click(function(elem){
            $("#search_request")[0].value = "";
            $(".pre-request").css("display","block");
            $(".pre-filter").css("display","none");
        });



        $('#button_probeall').click(function(e){
            
            $('#probeall_count').html(
                GLOBAL.results!=null? (GLOBAL.results.length!=null? GLOBAL.results.length : 1) : 0 
            );
            $('#probeall_modal').modal();
        });

        $('#probeall_modal .confirm').click(function(e){
            let probes = $(".probe");
            for(let i=0; i<probes.length; i++){
                probes[i].click();
            }
            $('#probeall_modal').modal('toggle');
        });

        // === Rename logic ===

        $(document).on("click",".rename",function(e){
            $("#renameModalSubject").val($(this).attr("subject"));
            $("#renameModalType").val($(this).attr("subt"));
            $("#renameModalAlias").val(decodeURIComponent(atob($(this).attr("ename"))));
            $("#renameModal").modal();
            $("#renameModalAlias").focus();
        });
        $('#renameModal').on('shown.bs.modal', function () {
           $('#renameModalAlias').trigger('focus')
        });
        $("#renameModalAlias").keypress( function (e) {
            var key = e.which || e.keyCode;
            if (key === 13) {
                $(".aliasconfirm").trigger('click');
            }   
        });

        $(document).on("click",".aliasconfirm",function(e){
            let subject = $("#renameModalSubject").val();
            let type = $("#renameModalType").val();
            let alias = $("#renameModalAlias").val();
            let url = null;
            let cell = null;

            if(type=="meth"){
                url = "../api/method/"+subject;
            }else if(type=="field"){
                url = "../api/field/"+subject;
            }else if(type=="class"){
                url = "../api/class/"+subject;
            }
            else
                return;

            $.ajax(
                url,
            {
                method: "put",
                data: { alias:alias },
                statusCode: {
                    200: function(data,err){
                        $('#renameModal').modal('toggle');

                    },
                    404: function(data,err){
                        alert(data.error);
                    }
                }
            });

        });

        // === END of Rename logic ===

        function setLocationQuery(){
            let q = location.href.indexOf('?');
            if(q==-1){
                location.query = "";
            } else{
                location.query = location.href.substr(
                    q+1,
                    location.href.length-q-1-location.hash.length
                );                
            }
        }

        setLocationQuery();
        //console.log(location,location.query.length>0);
        
        if(location.query.length>0){
            let o = location.query.indexOf("=");
            let tag = location.query.substr(0, o);
            let req = decodeURIComponent(atob(location.query.substr(o+1)));

            //console.log("parsing hash",tag,req);
            switch(tag){
                case "xrefcls":
                    $("#search_request")[0].value = 'call("calleed.enclosingClass.name:'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "xreffield":
                    $("#search_request")[0].value = 'call("calleed.__signature__:'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "xrefmeth":
                    $("#search_request")[0].value = 'call("calleed.__signature__:'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "method":
                    $("#search_request")[0].value = 'get.method("'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "field":
                    $("#search_request")[0].value = 'get.field("'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "class":
                    $("#search_request")[0].value = 'get.class("'+req+'")';
                    $("#button_search").trigger("click");
                    break;
                case "package":
                    $("#search_request")[0].value = 'class("package.name:^'+req+'")';
                    $("#button_search").trigger("click");
                    break;
            }
        }

        // hook configuration
/*
        $('#hookconfBefore').click(function(e){
            
            
        });

        $('#hookconfAfter').click(function(e){
            
            
        });

        $('#hookconfReplace').click(function(e){
            if($('#hookconfBefore').attr('checked')=='checked'){
                $('#hookconfBefore').click();
            }
            if($('#hookconfAfter').attr('checked')=='checked'){
                $('#hookconfAfter').click();
            }

            
        });*/
    });


    </script>

</body>

</html>
